import json
import threading
import time
import tkinter as tk
from tkinter import ttk

from dto.ReqLog import ReqLog
from util.Queue import data_queue, info_queue


class MainWin:
    def __init__(self):
        # 1.初始化主窗口
        self.win = tk.Tk()
        self.log = [];

        def initStyle():  # 初始化样式
            style = ttk.Style()
            # winnative clam alt default classic vista xpnative
            # style.theme_use('default')
            style.configure('icon.TButton', padding=(12, 0))
            style.configure('go.TButton', font=('Microsoft YaHei', '12', ''),  # bold
                            width=9)
            style.configure('gray.TCheckbutton', foreground='gray')

        initStyle()

        def initWin():
            self.win.title("MILVUS")
            # 窗口大小与位置
            w, h = 1000, 800  # 窗口初始大小与最小大小
            ws, hs = self.win.winfo_screenwidth(), self.win.winfo_screenheight()
            x, y = round(ws / 2 - w / 2), round(hs / 2 - h / 2)  # 初始位置，屏幕正中
            self.win.minsize(w, h)  # 最小大小
            self.win.geometry(f"{w}x{h}+{x}+{y}")  # 初始大小与位置
            self.win.protocol("WM_DELETE_WINDOW", self.onClose)  # 窗口关闭

        initWin()
        self.win.bind('<<QuitEvent>>', lambda *e: self.onClose())  # 退出事件

        self.notebook = ttk.Notebook(self.win, height=400)  # 初始化选项卡组件
        self.notebook.pack(expand=True, side='top', fill=tk.BOTH)  # 填满父组件

        def initTab1():  # 表格卡
            tabFrameTable = tk.Frame(self.notebook)  # 选项卡主容器
            # self.notebookTab.append(tabFrameTable)
            self.notebook.add(tabFrameTable, text=f'{"日志列表": ^10s}')
            # 表格主体
            fr2 = tk.Frame(tabFrameTable)
            fr2.pack(side='top', fill='both')
            self.table = ttk.Treeview(
                master=fr2,  # 父容器
                height=25,  # 表格显示的行数,height行
                columns=['type','req', 'resp', 'time'],  # 显示的列
                show='headings',  # 隐藏首列
            )
            self.table.pack(expand=True, side="left", fill='both')
            self.table.heading('type', text='类型')
            self.table.heading('req', text='请求')
            self.table.heading('resp', text='响应')
            self.table.heading('time', text='时间')
            self.table.column('type', width=5, minwidth=5)
            self.table.column('req', minwidth=40, stretch=tk.YES)
            self.table.column('resp', minwidth=40, stretch=tk.YES)
            self.table.column('time', width=10, minwidth=10)
            vbar = tk.Scrollbar(  # 绑定滚动条
                fr2, orient='vertical', command=self.table.yview)
            vbar.pack(side="left", fill='y')
            self.table["yscrollcommand"] = vbar.set

            def on_tree_click(event):
                items = self.table.selection();
                if len(items) == 0:
                    return
                # 获取当前选中的项
                id = items[0]
                item = self.table.item(id)["values"]
                self.panelOutput(item[1])
                self.panelOutput2(item[2])

            self.table.bind('<ButtonRelease-1>', on_tree_click)

            vFrame2 = tk.Frame(tabFrameTable)
            vFrame2.pack(side='right', fill='x', padx=3, pady=3)

            self.textOutput1 = tk.Text(vFrame2, height=30, width=70)
            self.textOutput1.pack(fill='both', side="left", padx=3, pady=3)

            self.textOutput2 = tk.Text(vFrame2, height=30, width=70)
            self.textOutput2.pack(fill='both', side="left", padx=3, pady=3)
        initTab1()

        def initTab2():  # 表格卡
            tabFrameTable = tk.Frame(self.notebook)  # 选项卡主容器
            # self.notebookTab.append(tabFrameTable)
            self.notebook.add(tabFrameTable, text=f'{"后台日志": ^10s}')
            # 表格主体
            fr3 = tk.Frame(tabFrameTable)
            fr3.pack(side='top', fill='both')

            self.textOutput3 = tk.Text(fr3, height=200, width=200)
            self.textOutput3.pack(fill='both', side="left", padx=3, pady=3)
        initTab2()

        # def initTextOutput():
        #
        # initTextOutput()

        def asyncMessage():
            threading.Thread(target=self.readMessage).start()
            threading.Thread(target=self.readMessage2).start()
        asyncMessage()

        self.gotoTop()
        self.win.mainloop()

    def readMessage(self):
        while True:
            # 休眠100毫秒 避免空循环占用CPU
            time.sleep(0.3)
            if not data_queue.empty():
                str = data_queue.get()
                j_data = json.loads(str)
                tableInfo = (
                    j_data["type"],
                    j_data["req"],
                    j_data["resp"],
                    j_data["time"])
                self.table.insert('', '0', values=tableInfo)
                items = self.table.get_children()
                row_count = len(items)
                if row_count > 15:
                    self.table.delete(items[-1])
    def readMessage2(self):
        while True:
            # 休眠100毫秒 避免空循环占用CPU
            time.sleep(0.3)
            # 一次取五条消息
            i = 5
            while i > 0 and not info_queue.empty():
                text = info_queue.get()
                self.log.append(text)
                i = i - 1;
            while len(self.log) > 100:
                self.log.pop(0)
            i = 0
            txt = ''
            while i < len(self.log):
                txt += self.log[len(self.log) -i - 1] + "\n";
                i += 1
            self.textOutput3.delete('1.0', tk.END)
            # 插入新内容
            self.textOutput3.insert(tk.END, txt)


    def onClose(self):  # 关闭软件
        self.exit()

    def gotoTop(self):  # 主窗置顶
        # 模式：自动弹出，或不满足静默模式要求
        if self.win.state() == 'iconic':  # 窗口最小化状态下
            self.win.state('normal')  # 恢复前台状态
        self.win.attributes('-topmost', 1)  # 设置层级最前
        geometry = self.win.geometry()  # 缓存主窗当前位置大小
        self.win.deiconify()  # 主窗获取焦点
        self.win.geometry(geometry)  # 若主窗正在贴边，获取焦点会退出贴边模式，所以重新设置位置恢复贴边

    # 写字板操作 =============================================

    def panelOutput(self, text):
        '''输出面板写入文字'''
        self.textOutput1.delete(1.0, tk.END)
        self.textOutput1.insert(tk.END, text)

    def panelOutput2(self, text):
        self.textOutput2.delete(1.0, tk.END)
        self.textOutput2.insert(tk.END, text)

    def errorOutput(self, title, msg='', highlight='red'):
        if not self.textOutput.get('end-2c') == '\n':  # 当前面板尾部没有换行，则加换行
            self.panelOutput('\n')
        self.panelOutput(title, highlight=highlight)  # 输出红色提示
        if msg:
            self.panelOutput('\n' + msg)
        self.panelOutput('\n')

    def panelClear(self):
        '''清空输出面板'''
        self.textOutput.delete('1.0', tk.END)

